
import * as request from "request-promise-native";
const sys_init_params = {
    encryptedTk: '05A98230D20F30CC74441032EA25BB2CB97FC034757D2F8FC5FB8222EFC2165E0C3D4517FD21DF5664E741CF74FC118950DFC9775420D10887A1457B75970BB57CBF20B30606AAE8B1E054D6D346A30FA3610F801F068903972D15B0F946E729436FB16C38610D6779D98DB64590C7201B2294F63DD606D1C826FBA375A93749C85CF1EBF4C5E67CD2BE1B0BA4651875B0E7ED54A16D8C086993248D9284338A8DC59EE12DB3460C1718EE031586ACAA73949C03EB8DBBFE0FE868439FAF986CFC20B8777D37F7A927C6A3B247FFF35026E19DF52A635E0A106A81E16EC162DB04503115F93BC3A6D292BAC1D88DDE0D36E60E5C89C8DB24C530EDF188B727C2',
    osName: 'ios',
    clientVersion: "29",
    currentKeyNo: '2',
    encryptedVid: "95E714CE3755E2916F238B2514024E766CEBF7A862E81D81",
    maxKeyNo: '3'
}

import { EventEmitter } from "events";

import * as qr from "qr-image"
export interface respone {
    resp: string,
    msg: string,
    params: { [key: string]: any }
}
export interface result<T> {
    success: boolean,
    errMsg: string,
    data: T
}


export interface res_userInfo {
    certStatus: string,
    certTp: string,
    cntryCode: string,
    eduStatus: string,
    encryptCdhdUsrId: string,
    faceRecgCert: string,
    faceRecgLoginSwitch: string,
    hceUserId: string,
    loginMobile: string,
    loginName: string,
    maskCertId: string,
    overSeaStatus: string,
    realName: string,
    respCode: string,
    respMsg: string,
    supDownloadBill: string,
    urid: string,
    welcomeWord: string,
    userSwitchs: {
        state: string,
        switchName: string
    }[]
}
export interface res_appInit {
    encryptedCk: string,
    encryptedVid: string,
    gray: string,
    respCode: string,
    respMsg: string,
    sid: string
}
export interface res_login {
    hceUserId: string,
    needVerify: "0" | "1",
    respCode: string,
    respMsg: string,
}
export interface res_cardInit {
    certificate: string;//收款码
    isRealName: "1" | "0",
    orderId: string,
    cardList: {
        bank: string,
        canPay: "1" | "0",
        cardType: string,
        color: string,
        iconRelUrl: string,
        pan: string,
        virtualCardNo: string
    }[];
}
export interface res_applayQrcode {
    certificate: string,
    orderId: string
}
export interface orderInList {
    orderId: string;
    amount: string;//0.10
    currencyUnit: string;//元
    orderStatus: string;
    orderTime: string;//"20181225 16:47:09"
    orderType: string;
    title: string;// "里*斌-收款"
    tn: string;//"03080000   00049992   566196122
}
export interface res_orderList {
    currentPage: string,
    pageSize: string,
    totalPage: string,
    uporders: orderInList[];
}
export interface res_orderDetail {

    mchntNm: string;
    orderDesc: string;//"*斌-收款"
    orderDetail: {
        bill_tp: string,//"21"
        business_tp: string,//"收款"
        collectionCard: string,// ""
        collectionCardInfo: string,// "招商银行(4413)"
        payCardInfo: string,//"招商银行(1231)"
        payUserName: string,//"*斌"
        postScript: string,//"收款"
        voucherNum: string,//"24181225604098294511"
        walletOrderId: string,//"20181225164709285381"
    },
    orderId: string;//"03080000   00049992   5661961225164709"
    orderStatus: string;//"A000"
    orderTime: string;//"2018-12-25 16:47:09"
    pointsAt: string;//"0"
    totalAmount: string;//"10"
    transAt: string;//"10"
}

export class yunshanfu extends EventEmitter {
    static EVENT_INITED = "EVENT_INITED";
    static EVENT_LOGINED = "EVENT_LOGINED";
    static EVENT_LOGINSMSNEEDED = "EVENT_LOGINSMSNEEDED";
    static EVENT_CARDINITED = "EVENT_CARDINITED";
    static EVENT_NEWORDER = "EVENT_NEWORDER";
    private _key: string = '9ea3a243c476be7b551d51e18f639aab0bc8da11e492dca7526c218fa1bb64fc9ea3a243c476be7b551d51e18f639aab9d08da1442b04e47';
    private _sid: string = ''
    private _gray: string = ''

    private _city_code: string = '110000';
    public cardInfo: {
        certificate: string;//收款码
        isRealName: boolean,
        orderId: string,
        cardList: {
            bank: string,
            canPay: boolean,
            cardType: string,
            pan: string,
            virtualCardNo: string
            color: string,
            iconRelUrl: string,

        }[];
    } = null;
    private _recentOrders: Map<string, orderInList> = new Map();
    public userInfo: res_userInfo = null;
    protected set key(value: string) {
        if (value && value.length > 0)
            this._key = value;
    }

    protected set sid(value: string) {
        if (value && value.length > 0)
            this._sid = value;
    }

    protected set gray(value: string) {
        if (value && value.length > 0)
            this._gray = value;
    }



    protected set city_code(value: string) {
        if (value && value.length > 0)
            this._city_code = value;
    }
    private inited = false;
    private logined = false;
    private _orderListInterval = null;
    constructor(autoInit: boolean = true) {
        super();
        if (autoInit) {
            this.Init().then(a => {
                this.inited = a.success;
                this.emit(yunshanfu.EVENT_INITED, a.success);

            });
        }
        this.on(yunshanfu.EVENT_LOGINED, () => {
            if (this._orderListInterval) {
                clearInterval(this._orderListInterval)
            }
            this.newOrders();
            this._orderListInterval = setInterval(() => {
                this.newOrders();
            }, 5000)
        })
    }
    public clear() {
        if (this._orderListInterval) {
            clearInterval(this._orderListInterval)
        }
        this.removeAllListeners();
    }

    protected respone2result(res: respone): result<any> {
        return {
            success: res.resp == "00",
            errMsg: res.resp == "00" ? "" : res.msg,
            data: res.params
        }
    }
    protected buildHeaders() {
        let headers = {
            'Connection': 'keep-alive',
            'User-Agent': 'iPhone CHSP',
            'Accept': '*/*',
            'Accept-Language': 'zh-Hans;q=1',
            'Content-Type': 'application/json'

        }
        if (this._city_code.length > 0) {
            headers['cityCd'] = this._city_code
        }
        if (this._gray.length > 0) {
            headers['gray'] = this._gray
        }
        if (this._sid.length > 0) {
            headers['sid'] = this._sid
        }
        if (this.userInfo && this.userInfo.urid && this.userInfo.urid.length > 0) {
            headers['urid'] = this.userInfo.urid
        }
        return headers;
    }
    private async decrypt(input: string) {

        let r = await request.post({
            //uri: "https://yunsfcrypt.azurewebsites.net/api/HttpTrigger1?code=b1SSwD1XpJJYb2dRth0xBFpae/7KhycqjDDeJSbpF3a4aHitaNNeAA==&action=decode",
            uri: "https://service-fcwd9l37-1257313909.ap-shanghai.apigateway.myqcloud.com/release/ysf",
            body: {
                action: "decode",
                key: this._key,
                input: input
            },
            json: true
        });
        return r;
    }
    private async initcrypt(input: string) {

        let r = await request.post({
            // uri: "https://yunsfcrypt.azurewebsites.net/api/HttpTrigger1?code=b1SSwD1XpJJYb2dRth0xBFpae/7KhycqjDDeJSbpF3a4aHitaNNeAA==&action=init",
            uri: "https://service-fcwd9l37-1257313909.ap-shanghai.apigateway.myqcloud.com/release/ysf",
            body: {
                action: "init",
                key: this._key,
                input: input
            }, json: true
        });
        return r;
    }
    private async postcrypt(input: string) {

        let r = await request.post({
            // uri: "https://yunsfcrypt.azurewebsites.net/api/HttpTrigger1?code=b1SSwD1XpJJYb2dRth0xBFpae/7KhycqjDDeJSbpF3a4aHitaNNeAA==&action=encode",
            uri: "https://service-fcwd9l37-1257313909.ap-shanghai.apigateway.myqcloud.com/release/ysf",
            body: {
                action: "postcrypt",
                key: this._key,
                input: input
            }, json: true
        });
        return r;
    }
    private async getcrypt(obj: Object) {

        let qs = {};
        for (let key in obj) {
            qs[key] = obj[key]
        }
        let r = await request.post({
            // uri: "https://yunsfcrypt.azurewebsites.net/api/HttpTrigger1?code=b1SSwD1XpJJYb2dRth0xBFpae/7KhycqjDDeJSbpF3a4aHitaNNeAA==&action=encode",
            uri: "https://service-fcwd9l37-1257313909.ap-shanghai.apigateway.myqcloud.com/release/ysf",
            body: {
                action: "getcrypt",
                key: this._key,
                input: qs
            }, json: true
        });
        return r;
    }
    public async Init(): Promise<result<res_appInit>> {
        if (this.inited) throw new Error("aleady Inited")
        let url = 'https://wallet.95516.com/app/inApp/sys/init'
        let headers = {
            'Connection': 'keep-alive',
            'User-Agent': 'iPhone CHSP',
            'Accept': '*/*',
            'Accept-Language': 'zh-Hans;q=1',
            'Content-Type': 'application/json',
        }
        let r = await request.get({
            uri: url,
            qs: sys_init_params,
            headers: headers,
            json: true // Automatically parses the JSON string in the response
        });
        if (r.resp == "00") {
            let params: res_appInit = <res_appInit>r.params;
            let s_key = await this.initcrypt(params.encryptedCk);
            let s_sid = params.sid;
            let s_gray = params.gray;
            //   let s_vid = await this.decrypt(params.encryptedVid);
            this.key = s_key;
            this.sid = s_sid;
            this.gray = s_gray

        }
        return this.respone2result(r);


    }
    protected async _requestGet(url: string, obj: Object): Promise<respone> {

        let qs = undefined;
        if (obj != null) {
            qs = await this.getcrypt(obj);

            // qs = {};
            // for (let key in obj) {
            //     qs[key] = (await this.encrypt(obj[key])).toUpperCase();
            // }
        }

        let r = await request.get({
            uri: url,
            qs: qs,
            headers: this.buildHeaders(),
            json: false // Automatically parses the JSON string in the response
        })
        let res = await this.decrypt(r);
        try {
            return JSON.parse(res);
        } catch (e) {
            return res;
        }
    }
    protected async _requestPost(url: string, obj: Object): Promise<respone> {

        let r = await request.post({
            uri: url,
            body: obj != null ? (await this.postcrypt(JSON.stringify(obj))).toUpperCase() : undefined,
            headers: this.buildHeaders(),
            json: false // Automatically parses the JSON string in the response
        })
        let res = await this.decrypt(r);
        try {
            return JSON.parse(res);
        } catch (e) {
            return res;
        }

    }

    //发短信
    protected async _login_sms(): Promise<result<undefined>> {
        let data = await this._requestPost('https://wallet.95516.com/app/inApp/user/sendLoginCode', {});
        return this.respone2result(data);
    }


    //# 验证手机短信
    protected async _verify_login_code(verify_code: string): Promise<result<undefined>> {
        let data = await this._requestPost('https://wallet.95516.com/app/inApp/user/verifyLoginCode', { smsCode: verify_code })
        return this.respone2result(data);
    }
    //# 登录接口,通知系统账号登录

    protected async _login(user: string, password: string): Promise<result<res_login>> {
        let data = await this._requestPost('https://wallet.95516.com/app/inApp/user/login', {
            password: password,
            loginName: user,
            cntryCode: '+86',
            imageId: '',
            imageCode: ''
        })
        return this.respone2result(data);
    }

    //# 获取用户信息接口
    protected async _init_user_info(): Promise<result<res_userInfo>> {
        let data = await this._requestGet('https://wallet.95516.com/app/inApp/user/get', null);
        if (data.resp == "00") {
            let user_id = (<res_userInfo>data.params).urid;
            this.userInfo = (<res_userInfo>data.params)
            this.logined = true;
            this.emit(yunshanfu.EVENT_LOGINED);
        }
        return this.respone2result(data);

    }

    //# 收款订单列表接口
    protected async _order_list(month: number): Promise<result<res_orderList>> {
        let data = await this._requestGet('https://wallet.95516.com/app/inApp/order/list', {
            month: month.toString(),
            pageSize: "10",//不会有变化，改变也没用
            currentPage: '1',
            orderStatus: '0',
            orderType: 'A30000'
        });
        return this.respone2result(data);
    }

    //# 收款订单详情接口
    protected async _order_detail(orderId: string): Promise<result<res_orderDetail>> {
        let data = await this._requestPost('https://wallet.95516.com/app/inApp/order/detail', {
            orderId: orderId,
            orderType: "21",
            transTp: "simple"
        })
        let res = this.respone2result(data);
        res.data.orderDetail = JSON.parse(res.data.orderDetail);
        return res;
    }

    //# 收款二维码初始化接口
    protected async _cardInit(): Promise<result<res_cardInit>> {
        let data = await this._requestGet('https://pay.95516.com/pay-web/restlet/qr/p2pPay/getInitInfo', {
            cityCode: this._city_code
        });
        return this.respone2result(data);
    }
    /*
    # 收款二维码生成接口
    # money: 收款金额,单位分
    # comments: 备注
    # virtual_card_no: 收款卡虚拟标志号
    # 返回中的 [params]-> [certificate] 就是收款链接,该链接生成的二维码即可以用ying行类app扫描支付*/
    protected async _applay_qrcode(money: number, comments: string, virtual_card_no: string): Promise<result<res_applayQrcode>> {
        let data = await this._requestGet('https://pay.95516.com/pay-web/restlet/qr/p2pPay/applyQrCode', {
            cityCode: this._city_code,
            comments: comments,
            txnAmt: money.toString(),
            virtualCardNo: virtual_card_no
        });
        return this.respone2result(data);
    }


    /**
     * 流模式下，true为登录成功，false为要手机验证码,,手机验证码已经直接发送
     * @param user 
     * @param pwd 
     */
    public async Login(user: string, pwd: string) {
        if (this.inited == false) throw (new Error("wait event EVENT_INIT"));
        if (this.logined == true) throw (new Error("already logined "));
        let info = await this._login(user, pwd);
        if (info.success == false) throw (new Error(info.errMsg));
        if (info.data.needVerify == "1") {
            await this.sendMeSms();
            return false;
        } else {
            let userinfo = await this._init_user_info();
            if (!userinfo.success) throw (new Error(userinfo.errMsg));

        }
        return true;
    }
    public async sendMeSms() {
        let smsinfo = await this._login_sms();
        if (!smsinfo.success) throw (new Error(smsinfo.errMsg));
        this.emit(yunshanfu.EVENT_LOGINSMSNEEDED);
    }
    /**
     * 流模式下，true为成功，false为验证码失败
     * @param sms 
     */
    public async verifySms(sms: string, autoSendSmsInFail: boolean = false) {
        let info = await this._verify_login_code(sms);
        if (info.success == false) {
            if (autoSendSmsInFail) {
                await this.sendMeSms();
            }
            return false;
        }
        let userinfo = await this._init_user_info();
        if (!userinfo.success) throw (new Error(userinfo.errMsg));
        return true;
    }

    public async cardInit() {
        let info = await this._cardInit()
        if (info.success == false) throw new Error(info.errMsg);
        this.cardInfo = {
            orderId: info.data.orderId,
            certificate: info.data.certificate,
            isRealName: info.data.isRealName == "1",
            cardList: []
        };
        info.data.cardList.forEach(a => {
            this.cardInfo.cardList.push({
                bank: a.bank,
                canPay: a.canPay == "1",
                cardType: a.cardType,
                pan: a.pan,
                color: a.color,
                iconRelUrl: a.iconRelUrl,
                virtualCardNo: a.virtualCardNo
            })
        });
        this.emit(yunshanfu.EVENT_CARDINITED);
    }
    public async getOrderList() {
        let info = await this._order_list(0);
        if (info.success == false) throw new Error(info.errMsg);
        return info.data.uporders
    }
    public async newOrders() {
        let info = await this._order_list(0);
        if (info.success == false) throw new Error(info.errMsg);
        let temp: Map<string, orderInList> = new Map();
        info.data.uporders.forEach(a => {
            if (this._recentOrders.has(a.orderId) == false) {
                this._order_detail(a.orderId).then(res => {
                    if (res.success) {
                        this.emit(yunshanfu.EVENT_NEWORDER, a, res.data);
                    } else {
                        this.emit(yunshanfu.EVENT_NEWORDER, a, null);
                    }

                })

            }
            temp.set(a.orderId, a);
        })
        this._recentOrders = temp;
    }
    public async getOrderDetail(orderId: string) {
        let info = await this._order_detail(orderId);
        if (info.success == false) throw new Error(info.errMsg);
        return info.data
    }
    public async createCardQrcode(money: number, virtual_card_no: string, comments: string = "") {
        let info = await this._applay_qrcode(money, comments, virtual_card_no);
        if (info.success == false) throw new Error(info.errMsg);
        var png: Buffer = <Buffer>qr.imageSync(info.data.certificate, { type: 'png' });
        return png.toString("base64")
    }
    public async createQrcode() {
        if (this.cardInfo) {
            var png: Buffer = <Buffer>qr.imageSync(this.cardInfo.certificate, { type: 'png' });
            return png.toString("base64")
        }
        return null;
    }
}

// function linstenModel() {
//     let d = new yunshanfu();
//     d.on(yunshanfu.EVENT_INITED, (isok: boolean) => {
//         if (!isok) return;
//         d.Login("123123", "123123");
//     })
//     d.on(yunshanfu.EVENT_LOGINSMSNEEDED, () => {
//         //输入验证码
//         d.verifySms("123123", true);
//     })
//     d.on(yunshanfu.EVENT_LOGINED, () => {

//         d.cardInit();
//     })
//     d.on(yunshanfu.EVENT_CARDINITED, () => {
//         //do somethings;
//     })
//     d.on(yunshanfu.EVENT_NEWORDER, (order: orderInList) => {
//         console.info(order)
//         //do somethings;
//     })
// }


// async function asyncModel() {
//     let c = new yunshanfu(false);

//     let info = await c.Init();
//     if (info.success == false) return;
//     try {
//         let isok = await c.Login("18980821922", "Wz19840311");
//         if (isok == false) {
//             while (await c.verifySms("123123") == false) {
//                 await c.sendMeSms();
//                 //填写新的验证码内容
//             }
//         }
//         await c.cardInit();
//     } catch (e) {

//     }


// }
//linstenModel();